<template>
  <div class="map-container">
    <div id="map" class="map"></div>
    
    <!-- 工具栏 -->
    <div class="toolbar">
      <button @click="addRandomPoints(50)">
        添加随机点({{ points.length }})
      </button>
      <button @click="clearPoints">
        清除所有点
      </button>
      <div class="distance-control">
        <span>聚合距离: {{ distance }}px</span>
        <el-slider 
          v-model="distance" 
          :min="20" 
          :max="200"
          @change="updateCluster">
        </el-slider>
      </div>
    </div>
  </div>
</template>

<script>
import 'ol/ol.css';
import Map from 'ol/Map';
import View from 'ol/View';
import { Tile as TileLayer, Vector as VectorLayer } from 'ol/layer';
import { XYZ, Vector as VectorSource, Cluster } from 'ol/source';
import { Point } from 'ol/geom';
import Feature from 'ol/Feature';
import { Style, Circle as CircleStyle, Fill, Stroke, Text, Icon, RegularShape } from 'ol/style';
import { fromLonLat, transform } from 'ol/proj';

export default {
  name: 'ClusterMap',
  
  data() {
    return {
      map: null,
      points: [],
      vectorSource: null,
      clusterSource: null,
      vectorLayer: null,
      distance: 40, // 聚合距离
      pointIcon: '/images/markers/PP_CJ.png', // 点位图标路径
      clusterStyles: {}
    };
  },

  mounted() {
    this.initMap();
  },

  methods: {
    initMap() {
      // 创建矢量数据源
      this.vectorSource = new VectorSource();
      
      // 创建聚合数据源
      this.clusterSource = new Cluster({
        distance: this.distance,
        source: this.vectorSource
      });

      // 创建矢量图层
      this.vectorLayer = new VectorLayer({
        source: this.clusterSource,
        style: (feature) => {
          const size = feature.get('features').length;
          
          // 单个点的样式
          if (size === 1) {
            // 获取原始点要素
            const originalFeature = feature.get('features')[0];
            return this.createPointStyle(originalFeature);
          }
          
          // 聚合点的样式
          return this.createClusterStyle(feature);
        }
      });

      // 创建地图
      this.map = new Map({
        target: 'map',
        layers: [
          new TileLayer({
            source: new XYZ({
              url: 'http://t{0-7}.tianditu.gov.cn/vec_w/wmts?' +
                'SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles' +
                '&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=8c88eba266a165eac9c085724708f2f9'
            })
          }),
          // 添加天地图文字标注图层
          new TileLayer({
            source: new XYZ({
              url: 'http://t{0-7}.tianditu.gov.cn/cva_w/wmts?' +
                'SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles' +
                '&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=8c88eba266a165eac9c085724708f2f9'
            })
          }),
          this.vectorLayer
        ],
        view: new View({
          center: fromLonLat([87.617733, 43.792818]), // 乌鲁木齐市中心坐标
          zoom: 13,
          // projection: 'EPSG:3857'  // 明确指定投影
        })
      });

      // 初始添加点
      this.addRandomPoints(50);
    },

    // 创建点位样式
    createPointStyle(feature) {
      const name = feature.get('name');
      return new Style({
        image: new Icon({
          src: this.pointIcon,
          scale: 1,
          anchor: [0.5, 1],
          anchorXUnits: 'fraction',
          anchorYUnits: 'fraction'
        }),
        text: new Text({
          text: name,
          offsetY: -25,
          fill: new Fill({
            color: '#fff'
          }),
          font: '12px sans-serif',
          textAlign: 'center',
          textBaseline: 'bottom',
          stroke: new Stroke({
            color: 'rgba(0, 0, 0, 0.6)',
            width: 3
          }),
          padding: [2, 5, 2, 5],
          backgroundFill: new Fill({
            color: 'rgba(0, 0, 0, 0.6)'
          }),
          backgroundStroke: new Stroke({
            color: 'rgba(255, 255, 255, 0.2)',
            width: 1
          })
        })
      });
    },

    // 添加随机点
    addRandomPoints(count = 20) {
      // 新疆范围
      const bounds = {
        minLon: 73.5,
        maxLon: 96.4,
        minLat: 34.4,
        maxLat: 49.2
      };

      const points = [];
      
      for (let i = 0; i < count; i++) {
        // 在新疆范围内随机生成点
        const lon = bounds.minLon + Math.random() * (bounds.maxLon - bounds.minLon);
        const lat = bounds.minLat + Math.random() * (bounds.maxLat - bounds.minLat);
        
        // 转换为Web墨卡托坐标
        const coordinates = fromLonLat([lon, lat]);
        
        const feature = new Feature({
          geometry: new Point(coordinates),
          name: `点位 ${this.points.length + i + 1}`,
          id: this.points.length + i + 1
        });
        
        feature.setStyle(this.createPointStyle(feature));
        points.push(feature);
      }
      
      this.vectorSource.addFeatures(points);
      this.points = this.points.concat(points);
    },

    // 清除所有点
    clearPoints() {
      this.vectorSource.clear();
      this.points = [];
    },

    // 更新聚合距离
    updateCluster() {
      this.clusterSource.setDistance(this.distance);
    },

    // 创建聚合样式
    createClusterStyle(feature) {
      const size = feature.get('features').length;
      let style = this.clusterStyles[size];
      
      if (!style) {
        const radius = Math.min(Math.max(10, Math.sqrt(size) * 4), 30);
        let color = '#409eff';
        
        if (size > 50) color = '#f56c6c';
        else if (size > 20) color = '#e6a23c';
        else if (size > 10) color = '#67c23a';
        
        style = new Style({
          image: new CircleStyle({
            radius: radius,
            fill: new Fill({
              color: color
            }),
            stroke: new Stroke({
              color: '#fff',
              width: 2
            })
          }),
          text: new Text({
            text: size.toString(),
            fill: new Fill({
              color: '#fff'
            }),
            font: 'bold 12px sans-serif'
          })
        });
        
        this.clusterStyles[size] = style;
      }
      
      return style;
    }
  }
};
</script>

<style scoped>
.map-container {
  width: 100%;
  height: 100vh;
  position: relative;
}

.map {
  width: 100%;
  height: 100%;
}

.toolbar {
  position: absolute;
  top: 10px;
  left: 10px;
  background: white;
  padding: 10px;
  border-radius: 4px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.15);
  z-index: 1000;
  min-width: 200px;
}

.toolbar button {
  margin: 0 5px;
  padding: 8px 15px;
  border: 1px solid #dcdfe6;
  background: white;
  cursor: pointer;
  border-radius: 4px;
  transition: all 0.3s;
  font-size: 14px;
  color: #606266;
}

.toolbar button:hover {
  color: #409EFF;
  border-color: #c6e2ff;
  background-color: #ecf5ff;
}

.distance-control {
  margin-top: 15px;
  padding: 10px;
  background: #f5f7fa;
  border-radius: 4px;
}

.distance-control span {
  display: block;
  margin-bottom: 8px;
  color: #606266;
  font-size: 14px;
}

:deep(.el-slider__runway) {
  margin: 8px 0;
}

:deep(.el-slider__bar) {
  background-color: #409EFF;
}

:deep(.el-slider__button) {
  border-color: #409EFF;
}
</style> 